home *** CD-ROM | disk | FTP | other *** search
- program investigate_header; {Investigate a Windows 3.1 EXE header}
- uses crt;
-
- type
- OLD_HEADER_TYPE =record
- ID_Word :word; {Better be MZ}
- Last_Page_Size :word; {Size of last page}
- Page_Count :word; {512 byte blocks}
- Rel_Table_Entries :word; {Entries in relocation table}
- Header_Size :word; {16 byte paragraphs}
- MINALLOC :word; {Min size program needs, 16 byte paragraphs}
- MAXALLOC :word; {Max size program will take, 16 byte paragraphs}
- Init_SS :word; {Initial stack (relocated)}
- Init_SP :word;
- Checksum :word; {Normally not used}
- Init_IP :word; {Entry point (relocated)}
- Init_CS :word;
- Reloc_Table_Offset :word; {Location of relocation table, from start of file}
- {If >=40H, then value at 3CH is offset to new style header}
- Overlay_No :word; {Overlay number, 0 for programs}
- Filler :array[$1C..$3B] of byte;
- New_Header_Offset :word;
- end;
-
- NEW_HEADER_TYPE =record
- Signature :word; {00 Better be NE}
- Linker_Version :byte; {02 Self-explanatory}
- Linker_Revision :byte; {03}
- Entry_Table_Offset :word; {04}
- Entry_Table_Length :word; {06}
- Reserved1a :word; {08}
- Reserved1b :word; {0A}
- Flags :word; {0C}
- Automatic_Data_Seg :word; {0E 0 if SINGLEDATA and MULTIPLEDATA not specified}
- Local_Heap_Size :word; {10 Initial local heap size in bytes}
- Stack_Size :word; {12 Initial stack size, in bytes}
- Init_IP :word; {14 Initial entry point}
- Init_CS :word; {16 Index to segment table!'}
- Init_SP :word; {18 Initial stack}
- Init_SS :word; {1A}
- Segment_Table_Entries:word; {1C Number of entries in segment table}
- Mod_Ref_Table_Entries:word; {1E Number of entries in module reference table}
- Non_NameTable_Entries:word; {20 Number of entries in non-resident name table}
- Seg_Table_Offset :word; {22 Offset to segment table, from start of new header}
- Resrc_Table_Offset :word; {24 Offset to resource table}
- Res_Name_Table_Offset:word; {26 Offset to resident name table}
- Mod_Ref_Table_Offset :word; {28 Offset to module reference table}
- Imp_Name_Table_Offset:word; {2A Offset to imported names table}
- Nrs_Name_Table_Offset:longint; {2C Offset to non-resident name table, from BEGINNING of file in bytes}
- Moveable_Entry_Pts :word; {30 Number of moveable entry points}
- Seg_Alignment :word; {32 Log base 2 of segment sector size, defailt=9-->512 bytes}
- Resource_Segments :word; {34 Specifies number of resource segments}
- Op_system :byte; {36 Flags indicate what operating system this file is for 0=unknown, 1=OS/2, 2=Windows}
- Flags2 :byte; {37}
- Fast_Load_Start :word; {38 Specifies start of fast load area}
- Fast_Load_End :word; {3A End of fast load area}
- Reserved2 :word; {3C}
- Win_Version :word; {3E Specifies windows version number}
- end;
-
- SEG_TABLE_TYPE =record
- Offset :word;
- Size :word;
- Attributes :word;
- Alloc :word;
- end;
-
- RES_INFO_TYPE =record
- ResType :word;
- Count :word;
- Reserved :longint;
- end;
-
- RES_NAME_INFO_TYPE =record
- Offset :word;
- Length :word;
- Flags :word;
- ID :word;
- Handle :word;
- Usage :word;
- end;
-
- ENTRY_MOVEABLE_TYPE =record
- Flags :byte;
- INT_3F :word;
- Segment :byte;
- Offset :word;
- end;
-
- ENTRY_FIXED_TYPE =record
- Flags :byte;
- Offset :word;
- end;
-
- var
- f :file;
- fname :string;
- fo :text;
- foname :string;
- old_header :OLD_HEADER_TYPE;
- new_header :NEW_HEADER_TYPE;
- seg_table :SEG_TABLE_TYPE;
- i,j :word;
- module_name :string;
- resident_name :string;
- res_info :RES_INFO_TYPE;
- res_name_info :RES_NAME_INFO_TYPE;
- resource_name :string;
- seg_align :longint;
- res_align :longint;
- Entry_Moveable :ENTRY_MOVEABLE_TYPE;
- Entry_Fixed :ENTRY_FIXED_TYPE;
-
- function hex(w:word):string;
- const h:array[0..15] of char=('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
- begin
- hex:=h[w div 4096] + h[(w div 256) and 15] + h[(w div 16) and 15] + h[w and 15];
- end;
-
- function imported_name(j:word):string;
- var
- s :string;
- n,i :word;
- begin
- n:=1;
- for i:=1 to j do
- begin
- seek(f,old_header.New_Header_Offset+new_header.Imp_Name_Table_Offset+n);
- blockread(f,s,255);
- if ord(s[0])>0 then n:=n+ord(s[0])+1;
- end;
- imported_name:=s;
- end;
-
- begin
- fname:=ParamStr(1);
- if ParamCount<>2 then AssignCRT(fo) else
- begin
- foname:=ParamStr(2);
- assign(fo,foname);
- end;
- rewrite(fo);
- assign(f,fname);
- reset(f,1); {open with 1 byte block}
- blockread(f,old_header,sizeof(old_header));
- if ParamCount<>2 then ClrScr;
- if old_header.ID_Word=ord('M')+256*ord('Z') then with old_header do
- begin
- writeln(fo,'Page count = ',Page_Count);
- writeln(fo,'Last page size = ',Last_Page_Size);
- writeln(fo,'Relocation table entries = ',Rel_Table_Entries);
- writeln(fo,'Header size (bytes) = ',Header_Size*16);
- writeln(fo,'MINALLOC (16 byte paragraphs) = ',MINALLOC);
- writeln(fo,'MAXALLOC (16 byte paragraphs) = ',MAXALLOC);
- writeln(fo,'Initial SS:SP = ',hex(Init_SS),':',hex(Init_SP),'H');
- writeln(fo,'Initial CS:IP = ',hex(Init_CS),':',hex(Init_SP),'H');
- writeln(fo,'Checksum = ',hex(Checksum),'H');
- writeln(fo,'Relocation Table Offset = ',Reloc_Table_Offset);
- writeln(fo,'Overlay number = ',Overlay_No);
- end
- else
- begin
- writeln(fo,'This is not an EXE file!!');
- halt;
- end;
- if old_header.Reloc_Table_Offset>=$40 then
- begin
- writeln(fo,'New Header Offset = ',old_header.New_Header_Offset);
- writeln(fo);
- writeln(fo,'This is a Windows or OS/2 executable file!');
- writeln(fo,'Press any key to view new-style header.');
- if ParamCount<>2 then if ReadKey=' ' then;
- seek(f,old_header.New_Header_Offset);
- blockread(f,new_header,sizeof(new_header));
- if ParamCount<>2 then clrscr;
- with new_header do {Display header info}
- begin
- writeln(fo,'Header type = ',char(Signature and 255),char(Signature shr 8));
- writeln(fo,'Initial CS:IP = #',Init_CS,':',hex(Init_IP),'H');
- writeln(fo,'Initial SS:SP = #',Init_SS,':',hex(Init_SP),'H Size = ',Stack_Size);
- writeln(fo,'Segment table entries = ',Segment_Table_Entries);
- writeln(fo,'Module reference table entries = ',Mod_Ref_Table_Entries);
- writeln(fo,'Moveable entry points = ',Moveable_Entry_Pts);
- writeln(fo,'Resource segments = ',Resource_Segments);
- writeln(fo,'Automatic data segment = ',Automatic_Data_Seg);
- writeln(fo,'Fast load offset = ',Fast_Load_Start);
- case op_system of
- 1 : writeln(fo,'This is an OS/2 program.');
- 2 : writeln(fo,'This is a Windows program.');
- end;
- end;
- writeln(fo);
- write(fo,'Modules referenced: ');
- for i:=1 to new_header.Mod_Ref_Table_Entries do
- begin
- seek(f,old_header.New_Header_Offset+new_header.Mod_Ref_Table_Offset+2*(i-1));
- blockread(f,j,2);
- seek(f,old_header.New_Header_Offset+new_header.Imp_Name_Table_Offset+j);
- blockread(f,module_name,256);
- write(fo,module_name,' ');
- end;
- writeln(fo);
- writeln(fo,'Press any key to continue.');
- if ParamCount<>2 then if ReadKey=' ' then ;
- writeln(fo);
- write(fo,'Resident names: ');
- j:=0;
- repeat
- seek(f,old_header.New_Header_Offset+new_header.Res_Name_Table_Offset+j);
- blockread(f,resident_name,256);
- j:=j+ord(resident_name[0])+2;
- write(fo,resident_name,' ');
- until resident_name[0]=#0;
- writeln(fo);
- writeln(fo,'Non-resident names: ');
- j:=0;
- repeat
- seek(f,new_header.NRS_Name_Table_Offset+j);
- blockread(f,resident_name,256);
- j:=j+ord(resident_name[0])+3;
- writeln(fo,' ',resident_name);
- until resident_name[0]=#0;
- writeln(fo);
- seg_align:=1;
- if new_header.Seg_Alignment<>0 then for i:=1 to new_header.Seg_Alignment do seg_align:=2*seg_align
- else seg_align:=512;
- writeln(fo,'Segments: (Alignment=',seg_align,'(',new_header.Seg_Alignment,'))');
- writeln(fo,'Offset Length Alloc Size Attributes');
- for i:=1 to new_header.Segment_Table_Entries do
- begin
- seek(f,old_header.New_Header_Offset+new_header.Seg_Table_Offset+8*(i-1));
- blockread(f,seg_table,sizeof(seg_table));
- write(fo,seg_table.offset:5,seg_table.size:9,seg_table.alloc:13,' ');
- if seg_table.attributes and 1 = 1 then write(fo,'DATA ') else write(fo,'CODE ');
- if seg_table.attributes and 2 = 2 then write(fo,'Allocated ');
- if seg_table.attributes and 4 = 4 then write(fo,'Loaded ');
- if seg_table.attributes and 16 = 16 then write(fo,'Moveable ') else write(fo,'Fixed ');
- if seg_table.attributes and 32 = 32 then write(fo,'Shareable ');
- if seg_table.attributes and 64 = 64 then write(fo,'Preload ');
- if seg_table.attributes and 128 = 128 then write(fo,'Exec_Only/Read_Only ');
- if seg_table.attributes and 256 = 256 then write(fo,'Contains_Rel_Data ');
- if seg_table.attributes and 4096 = 4096 then write(fo,'Discardable ');
- writeln(fo);
- end;
- writeln(fo);
- if new_header.Resource_segments<>0 then
- begin
- seek(f,old_header.New_Header_Offset+new_header.Resrc_Table_Offset);
- blockread(f,j,2);
- res_align:=1;
- for i:=1 to j do res_align:=2*res_align;
- writeln(fo,'Resources: (Alignment=',res_align,')');
- writeln(fo,'Offset Length ID');
- repeat
- blockread(f,res_info,sizeof(res_info));
- if Res_Info.ResType<>0 then for i:=1 to res_info.count do
- begin
- blockread(f,res_name_info,sizeof(res_name_info));
- write(fo,res_name_info.Offset:5,'(',res_align*res_name_info.Offset,')',res_name_info.length:10,' ');
- if res_name_info.ID>=$8000 then writeln(fo,res_name_info.ID-$8000)
- else
- begin
- j:=filepos(f);
- seek(f,old_header.New_Header_Offset+new_header.Resrc_Table_Offset+res_name_info.ID);
- blockread(f,resource_name,256);
- writeln(fo,resource_name);
- seek(f,j);
- end;
- end;
- until Res_Info.ResType=0;
- end
- else writeln(fo,'There are no resources.');
- writeln(fo);
- writeln(fo,'Entry table:');
- seek(f,old_header.New_Header_Offset+new_header.Entry_Table_Offset);
- repeat
- blockread(f,j,2);
- if j shr 8 = $FF then
- begin
- writeln(fo,'Moveable:');
- for i:=1 to j and $FF do
- begin
- blockread(f,Entry_Moveable,sizeof(Entry_Moveable));
- writeln(fo,Entry_Moveable.Segment,':',hex(Entry_Moveable.Offset));
- end;
- end;
- if j shr 8 = $FE then
- begin
- writeln(fo,'Constant:');
- end;
- if not (j shr 8 in [0,$FE,$FF]) then
- begin
- writeln(fo,'Fixed: (',j and $FF,')');
- for i:=1 to j and $FF do
- begin
- blockread(f,Entry_Fixed,sizeof(Entry_Fixed));
- writeln(fo,j shr 8,':',hex(Entry_Fixed.Offset));
- end;
- end;
- until (j and $FF) = 0;
- end
- else writeln(fo,'This is a standard DOS EXE file.');
- writeln(fo);
- writeln(fo,'Press any key to continue.');
- if ParamCount<>2 then if ReadKey=' ' then ;
- close(fo);
- close(f);
- end.
-